load("//tools/workspace:os.bzl", "determine_os")
load("//tools/workspace:execute.bzl", "execute_or_fail", "which")

def _find_library(repo_ctx, compiler, lib_name):
    return execute_or_fail(
        repo_ctx,
        [compiler, "--print-file-name=" + lib_name],
    ).stdout.strip()

def _gfortran_impl(repo_ctx):
    """Locate gfortran and alias it to `:compiler`; locate libgfortran and
    libquadmath and alias then to `:runtime.`"""

    # Find the compiler.
    compiler = str(which(repo_ctx, "gfortran"))
    if not compiler:
        fail("Could not find gfortran")
    repo_ctx.symlink(compiler, "gfortran-found")

    # Find the runtime libraries based on the OS.
    os_result = determine_os(repo_ctx)
    if os_result.error != None:
        fail(os_result.error)
    if os_result.is_macos or os_result.is_macos_wheel:
        suffix = ".dylib"
    else:
        suffix = ".so"
    libgfortran = "libgfortran{}".format(suffix)
    libgfortran_path = _find_library(repo_ctx, compiler, libgfortran)

    # The cc_library linking is different on Ubuntu vs macOS.
    if os_result.is_macos or os_result.is_macos_wheel:
        srcs = []
        linkopts = [
            "-L{}".format(repo_ctx.path(libgfortran_path).dirname),
            "-ldl",
            "-lgfortran",
        ]
        if os_result.macos_arch_result != "arm64":
            linkopts.append("-lquadmath")
    else:
        libquadmath = "libquadmath{}".format(suffix)
        libquadmath_path = _find_library(repo_ctx, compiler, libquadmath)
        repo_ctx.symlink(libgfortran_path, libgfortran)
        repo_ctx.symlink(libquadmath_path, libquadmath)
        srcs = [libgfortran, libquadmath]
        linkopts = ["-ldl"]

    # Inquire which version we found.
    dumpversion = execute_or_fail(repo_ctx, [compiler, "-dumpversion"]).stdout
    repo_ctx.file("version.bzl", content = "MAJOR = {}\n".format(
        int(dumpversion.strip()),
    ))

    # Emit the build file and return.
    BUILD = """
    # DO NOT EDIT: generated by gfortran_repository().

    load("@drake//tools/skylark:cc.bzl", "cc_library")

    # libgfortran: GPL-3.0-or-later WITH GCC-exception-3.1.
    # libquadmath: LGPL-2.0-or-later.
    licenses(["restricted"])  # See above for details.

    sh_binary(
        name = "compiler",
        srcs = ["gfortran-found"],
        visibility = ["//visibility:public"],
    )
    cc_library(
        name = "runtime",
        srcs = {},
        linkopts = {},
        visibility = ["//visibility:public"],
    )
    """.format(srcs, linkopts).replace(
        # Strip leading indentation.
        "\n    ",
        "\n",
    )
    repo_ctx.file("BUILD.bazel", content = BUILD)

gfortran_repository = repository_rule(
    local = True,
    configure = True,
    implementation = _gfortran_impl,
)
